<?php
/**
 * JSON返回结果
 * @param  string  $msg    提示信息
 * @param  integer $status 自定义状态码
 *                         0：成功
 *                         1：常规错误
 *                         2：token过期
 *
 * @param  array   $data   返回的数据
 * @param  integer $code   服务器响应码
 * @return json
 */
function json($msg='',$status=0,$data=[],$code=null,$url=''){
	if(is_array($msg)){
        $arr=$msg;
		$msg=isset($arr['msg'])?$arr['msg']:'';
		$status=isset($arr['status'])?$arr['status']:$status;
		$data=isset($arr['data'])?$arr['data']:$data;
		$code=isset($arr['code'])?$arr['code']:$code;
		$url=isset($arr['url'])?$arr['url']:$url;
	}
	if(empty($code))$code=response()->getCode();
	if(empty($data)){
		$data=null;
	}
	$result=[
		'code'=>$code,
		'status'=>$status,
		'msg'=>$msg,
		'data'=>$data,
		'url'=>$url,
	];
	return json_encode($result,JSON_UNESCAPED_UNICODE);
}
/**
 * 统一的密码加密函数
 * @param  string $pwd 原始密码
 * @return string      加密后密码
 */
function encrypt_pwd($pwd=''){
	$key='这是一个加密所用的秘钥,生产环境中请慎重修改！';
	return md5($key.$pwd);
}
/**
 * 短信发送
 * @param  string|array $tel     手机号码|多个
 * @param  string $content  消息内容
 * @return array
 */
function sms($tel=null,$content=null){
    if(is_null($tel)||is_null($content)){
        return ;
    }
    if(is_array($tel)){
        $tel=implode(',',$tel);
    }
    $suffix='【微手】';
    $url='http://sms.bamikeji.com:8890/mtPort/mt/normal/send';
    $data=[
        'uid'=>'2268',
        'passwd'=>'149c2a0a11a5de464e64d9731d9506a4',
        'phonelist'=>$tel,
        'content'=>$content.$suffix,
    ];
    $url.='?'.http_build_query($data);
    $rs=_curl($url,false);
    if(is_string($rs)){
        $rs=json_decode($rs,true);
    }
    return $rs;
}
/**
 * 微信app支付（依赖 extend/weixinpay/）
 * @param  array  $biz_content 订单说明
 * @return string
 */
function weixinpay($biz_content=[]){
    $app_id=config('config.weixinpay_app_id');
    $mch_id=config('config.weixinpay_mch_id');
    $key=config('config.weixinpay_key');
    $notify_url=url('index/order/weixinpay',[],'html',request()->domain());
    $wxpay=new \weixinpay\Weixinpay($app_id,$mch_id,$key);
    return $wxpay->weixinpay($biz_content,$notify_url);
    
}
/**
 * 支付宝app支付（依赖 extend/alipay/）
 * @param  array  $biz_content 订单说明
 * @param  string $notify_url  回调地址
 * @return string
 */
function alipay($biz_content=[],$notify_url=null){
    $notify_url=url('index/order/alipay',[],'html',request()->domain());
    $biz_content=array_merge([
        // 'subject'=>'商品说明',
        // 'out_trade_no'=>'商户网站唯一订单号',
        // 'total_amount'=>'订单总金额，单位为元，精确到小数点后两位',
        'product_code'=>'QUICK_MSECURITY_PAY',
        'goods_type'=>0, //0—虚拟类商品，1—实物类商品
    ],$biz_content);

    $param=[
        'app_id'=>config('config.alipay_app_id'),
        'method'=>'alipay.trade.app.pay',
        'charset'=>'utf-8',
        'sign_type'=>'RSA2',
        'timestamp'=>date('Y-m-d H:i:s'),
        'version'=>'1.0',
        'notify_url'=>$notify_url,
        'biz_content'=>json_encode($biz_content),
    ];
    
    $c = new \alipay\AopClient;

    $paramStr = $c->getSignContent($param);//组装请求签名参数
    $keyPath=env('root_path').'extend/alipay/alipay_private_key.txt';
    $sign = $c->alonersaSign($paramStr, $keyPath, $param['sign_type'],true);
    $param['sign'] = $sign;
    $str = $c->getSignContentUrlencode($param);//最终请求参数
    
    return $str;
}
function alipayClient(){
    $keyPath=env('root_path').'extend/alipay/alipay_private_key.txt';
    $c = new \alipay\AopClient;
    $c->appId=config('config.alipay_app_id');
    $c->rsaPrivateKeyFilePath=$keyPath;
    $c->alipayrsaPublicKey = config('config.alipay_public_key_sha264');
    $c->signType='RSA2';
    return $c;
}
function alipayTransfer($biz_content=[]){
    $biz_content=array_merge([
        // 'out_biz_no'=>'商户网站唯一转账订单号',
        // 'amount'=>'转账金额',
        // 'payee_account'=>'收款方账户',
        'payee_type'=>'ALIPAY_LOGONID',
        'product_code'=>'QUICK_MSECURITY_PAY',
    ],$biz_content);
    $request=new \alipay\request\AlipayFundTransToaccountTransferRequest;
    $request->setBizContent(json_encode($biz_content));
    
    $c = alipayClient();
    $res=$c->execute($request);
    return objectToArray($res);
}
function alipayTransQuery($biz_content=[]){
    $biz_content=array_merge([
        // 'out_biz_no'=>'商户网站唯一转账订单号',
        // 'order_id'=>'支付宝转账单据号',
    ],$biz_content);
    $request=new \alipay\request\AlipayFundTransOrderQueryRequest;
    $request->setBizContent(json_encode($biz_content));
    
    $c = alipayClient();
    $res=$c->execute($request);
    return objectToArray($res);
}
/**
  * 数组转xml
  * @param array $data
  * @return string
  */
function arrayToXml($data){
    if(!is_array($data) || count($data) <= 0){
        return false;
    }
    $xml = "<xml>";
    foreach ($data as $key=>$val){
        if (is_numeric($val)){
            $xml.="<".$key.">".$val."</".$key.">";
        }else{
            $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
        }
    }
    $xml.="</xml>";
    return $xml;
}
function objectToArray($object=[]){
    if(is_object($object)){
        $object=(array)$object;
    }
    if(is_array($object)){
        foreach ($object as $k => $v) {
            $object[$k]=objectToArray($v);
        }
    }
    return $object;
}
/**
  * XML转数组
  * @param unknown $xml
  * @return mixed
  */
function xmlToArray($xml){
    //将XML转为array
    return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
}
/**
 * curl请求
 * @param  string  $curl   请求地址
 * @param  boolean $https  是否SSL
 * @param  string  $method 请求方式
 * @param  array   $data   POST请求数据
 * @return string
 */
function _curl($curl,$https=true,$method="get",$data=[],$headers=[]){
    $ch=curl_init();
    curl_setopt($ch, CURLOPT_URL, $curl);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if($https){
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    }else{
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    }
    if($method=="post"){
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    }
    if(!empty($headers)){
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $content=curl_exec($ch);
    curl_close($ch);
    return $content;
}


/**
 * @desc 数据导出到excel(csv文件)
 * @param $filename 导出的csv文件名称 如date("Y年m月j日").'-test.csv'
 * @param array $dataArray 所有列数据
 * @param array $tileArray 所有列名称
 */
function exportToExcel($filename, $dataArray=[], $tileArray=[]){
    ini_set('memory_limit','512M');
    ini_set('max_execution_time',0);
    ob_end_clean();
    ob_start();
    header("Content-Type: text/csv");
    header("Content-Disposition:filename=".$filename);
    $fp=fopen('php://output','w');
    //fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));//转码 防止乱码(比如微信昵称(乱七八糟的))
    if(!empty($tileArray)){
        foreach ($tileArray as $k=> $value){
            //这里将utf-8转为GB2312编码进行保存
            $tileArray[$k] = iconv("UTF-8", "GB2312//IGNORE", ' '.$value);  
        }
        fputcsv($fp,$tileArray);
    }
    $index = 0;
    foreach ($dataArray as $item) {
        if($index==1000){
            $index=0;
            ob_flush();
            flush();
        }
        $index++;
        foreach ($item as $k=> $value){
            $item[$k] = iconv("UTF-8", "GB2312//IGNORE", $value);
        }
        fputcsv($fp,$item);
        unset($item);
    }

    ob_flush();
    flush();
    ob_end_clean();
}
/**
 * 个人所得税扣税
 * @param  integer $money     总收入
 * @param  integer $fee       用户本次金额
 * @param  integer $baseMoney 起征点
 * @return ['扣税金额','税后金额','税前金额']
 */
function tax($money=0,$fee=0){
    $baseMoney=5000;
    $f=[
        '80000'=>[45,15160],
        '55000'=>[35,7160],
        '35000'=>[30,4410],
        '25000'=>[25,2660],
        '12000'=>[20,1410],
        '3000'=>[10,210],
        '0'=>[3,0],
    ];
    $fmoney=$money+$fee-$baseMoney;

    $tax=0;
    if($fmoney>0){
        foreach ($f as $k => $v) {
            if($fmoney>$k){
                $tax=$fmoney*$v[0]/100-$v[1];
                break;
            }
        }
    }
    if($fee>0){
        $res=tax($money);
        $money=$fee;
        $tax-=$res[0];
    }
    return [$tax,$money-$tax,$money];
}
/**
 * 用于子集递推
 * @param  array  $arr    所有数据
 * @param  integer $pid    初始父级ID
 * @param  string  $pidKey 父级ID字段名
 * @return array
 */
function node_merge($arr,$pid=0,$pidKey='pid'){
	$rs=[];
	foreach ($arr as $k => $v) {
		if($v[$pidKey]===$pid){
			$childs=node_merge($arr,$v['id'],$pidKey);
			if(!empty($childs)){
				$v['children']=$childs;
			}
			$rs[]=$v;
		}
	}
	return $rs;
}

// 各类处理方法统一返回数据格式
function error($msg='操作失败!',$code=1,$data=[]){
	return [
		'success'=>false,
		'msg'=>$msg,
		'code'=>$code, // 成功返回 0 返回 1000 以上的 均建议提示用户
		'data'=>$data,
	];
}
function success($msg='操作成功!',$code=0,$data=[]){
	return [
		'success'=>true,
		'msg'=>$msg,
		'code'=>$code, // 成功返回 0 返回 1000 以上的 均建议提示用户
		'data'=>$data,
	];
}
/**
 * 增加一个时长后返回到期时间戳
 * （该方法用于用户购买会员时计算使用）
 * @param integer $_y 年
 * @param integer $_m 月
 * @param integer $_d 天
 * @param boolean $isDiff 是否返回时间段长
 */
function addDuration($_y=0,$_m=0,$_d=0,$isDiff=false){
    $time=time();
    $y=date('Y',$time)+$_y;
    $m=date('m',$time)+$_m;
    $d=date('d',$time)+$_d;
    if($d>31){
        $m+=floor($d/31);
        $d=$d%31;
    }
    if($m>12){
        $y+=floor($m/12);
        $m=$m%12;
    }
    $h=date('H',$time);
    $i=date('i',$time);
    $s=date('s',$time);
    $str="{$y}-{$m}-{$d} {$h}:{$i}:{$s}";
    $endTime=strtotime($str);
    return $isDiff?$endTime-$time:$endTime;
}

/**
 * Redis 操作
 * @param  function $fun 可以接收一个函数 函数注入一个参数(Redis的实例)
 * @return void
 */
function redis($fun=null){
    //ini_set('default_socket_timeout', -1);
    $redis = new \Redis();
    $redis -> pconnect(config('cache.redis.host'),config('cache.redis.port'));
    $redis -> auth(config('cache.redis.password'));
    if(empty($fun)){
        return $redis;
    }
    call_user_func($fun,$redis);
    $redis->close();
}
/**
 * 通过event、action获取配置中的 任务名称分类
 * @var $event
 * @var $action
 */
function getTaskEvent($event=null,$action=null,$config=[]){
	if(is_null($event)||is_null($action)){
		return [];
	}
	$taskConfig=empty($config)?config('task.'):$config;
	$task=[];
	foreach ($taskConfig as $v) {
		if($v['event']==$event){
			$task['group']=$v['title'];
			foreach ($v['children'] as $c) {
				if($c['action']==$action){
					$task['nav']=$c['title'];
					$task['type']=$c['type'];
				}
			}
		}
	}
	if(!isset($task['nav'])){
		return [];
	}
	return $task;
}

/**
 * 日志记录
 * https://github.com/katzgrau/KLogger
 * @param  string $level PSR-3 规范错误级别 参考下列
 * ['debug','error','info','warning','notice','alert','critical','emergency']
 * @param  string $message 日志内容信息
 * @param  array  $data    额外数据
 * @return void
 */
function logger($level,$message='',$data=[]){
    $path=env('root_path').'/logs/'.date('Y-m');
    $logger = new Katzgrau\KLogger\Logger($path);
    $logger->$level($message,$data);
}
/**
 * 遍历文件夹
 * @param  string  $dir  初始地址
 * @param  boolean $loop 是否全部遍历
 * @return array
 */
function read_files($dir,$loop=false){
    if(!is_dir($dir)) return false;
    $handle = opendir($dir);
    $rs=[
      'dir'=>[],
      'file'=>[],
    ];
    if($handle){
        while(($file = readdir($handle)) !== false){
            $temp = $dir.DIRECTORY_SEPARATOR.$file;
            //如果不加  $file!='.' && $file != '..'  则会造成把$dir的父级目录也读取出来
            if(is_dir($temp) && $file!='.' && $file != '..'){
                array_push($rs['dir'],$file);
                if($loop)read_all($temp,$loop);
            }else{
                if($file!='.' && $file != '..'){
                  array_push($rs['file'],$file);
                }
            }
        }
    }
    return $rs;
}
/**
 * 给图片加水印
 * 实例参考：single/Index/share
 * @param  string  $baseMap     底图路径
 * @param  string  $watermark   水印路径
 * @param  string  $newImage    新生成的图片路径
 * @param  double  $marginLeft  左边距
 * @param  double  $marginTop   上边距
 * @param  double  $watermark_w 水印宽度
 * @param  double  $watermark_h 水印高度
 * @param  integer $scale       水印是底图的比例
 * @return void
 */
function imgCopy($baseMap,$watermark,$newImage,$options=[]){
    $options=array_merge([
        'marginLeft'=>null,
        'marginTop'=>null,
        'watermark_w'=>null,
        'watermark_h'=>null,
        'scale'=>5,
        'text'=>null,
        'text_rgba'=>[255,255,255,0],
        'text_weight'=>20,
        'text_l'=>0,
        'text_t'=>0,
    ],$options);
    extract($options);

    $QR = imagecreatefromstring(file_get_contents($baseMap)); 
    $logo = imagecreatefromstring(file_get_contents($watermark));

    $QR_width = imagesx($QR);//底图宽度 
    $QR_height = imagesy($QR);//底图高度 

    $logo_width = imagesx($logo);//水印图片宽度 
    $logo_height = imagesy($logo);//水印图片高度 
    if(is_null($watermark_w)||$watermark_w==='null'){
        $watermark_w=$QR_width/$scale;
        if(is_null($watermark_h)||$watermark_h==='null'){
            $_scale = $logo_width/$watermark_w;
            $watermark_h = $logo_height/$_scale;
        }
    }
    if(is_null($watermark_h)||$watermark_h==='null'){
        $watermark_h=$QR_width/$scale;
        if(is_null($watermark_w)||$watermark_w==='null'){
            $_scale = $logo_height/$watermark_h;
            $watermark_w = $logo_width/$_scale;
        }
    }
    if(is_null($marginLeft)||$marginLeft==='null'){
        $marginLeft=($QR_width - $watermark_w) / 2;
    }
    if(is_null($marginTop)||$marginTop==='null'){
        $marginTop=($QR_height - $watermark_h) / 2;
    }
    //重新组合图片并调整大小 
    // 底图、水印、左边距、右边距、
    imagecopyresampled($QR, $logo, $marginLeft, $marginTop, 0, 0, $watermark_w, 
    $watermark_h, $logo_width, $logo_height);

    //写入文字
    if(!is_null($text)&&$text!=='null'){
        $col = imagecolorallocatealpha($QR,$text_rgba[0],$text_rgba[1],$text_rgba[2],$text_rgba[3]);
        imagettftext($QR,$text_weight,0,$text_l,$text_t,$col,"simkai.ttf",$text);
    }
    imagepng($QR, $newImage);
}

function getWeek($offset=0){
    $w=date('w');
    $weekTime=strtotime(date('Y-m-d'))+86400+$offset;
    $weekEndTime=$weekTime;
    if($w<=0){
        $w=7;
    }
    $weekTime-=86400*$w;
    $weekEndTime+=86400*(7-$w);
    return [$weekTime,$weekEndTime];
}
/**
 * 对多媒体 路径转换
 * @param  string $val 路径
 * @return string
 */
function images($val=null){
	if(is_null($val))return request()->domain().'/uploads';
	if(preg_match('/^(https?:)?\/\//',$val)){
		return $val;
	}
	return request()->domain().'/uploads'.$val;
}
// 性别转换
function sex($val=2){
	$sex=['女','男','保密'];
	return $sex[$val];
}
/**
 * 引入静态文件 公共路径设置
 * @return [type] [description]
 */
function _static(){
	echo "/static";
}
/**
 * 打印调试数据
 * @param  mixed   $arr 打印的数据
 * @param  boolean $die 是否停止程序
 * @return void
 */
function p(){
	$args=func_get_args();
	echo "<pre>";
	foreach ($args as $v) {
		echo "<br><br>";
		print_r($v);
	}
	echo "</pre>";
}
function dump(){
	call_user_func_array('p', func_get_args());
	die;
}
/**
 * 通过经纬度获取MAC地址
 * http://www.cellocation.com/
 * @param  [type] $lat [description]
 * @param  [type] $lng [description]
 * @return [type]      [description]
 */
function getMAC($lat,$lng,$mode='mac'){
    $curl="http://api.cellocation.com:81/rewifi/?lat=$lat&lon=$lng&n=10";
    if($mode=='mnc'){
        $curl="http://api.cellocation.com:81/recell/?lat=$lat&lon=$lng&n=10";
    }
    $res=_curl($curl,false);
    if(is_string($res)){
        $res=json_decode($res,true);
    }
    return $res;
}
function utf8_bytes($cp){
    if ($cp > 0x10000){
        # 4 bytes
        return chr(0xF0 | (($cp & 0x1C0000) >> 18)).
            chr(0x80 | (($cp & 0x3F000) >> 12)).
            chr(0x80 | (($cp & 0xFC0) >> 6)).
            chr(0x80 | ($cp & 0x3F));
    }elseif($cp > 0x800){
        # 3 bytes
        return  chr(0xE0 | (($cp & 0xF000) >> 12)).
            chr(0x80 | (($cp & 0xFC0) >> 6)).
            chr(0x80 | ($cp & 0x3F));
    }elseif($cp > 0x80){
        # 2 bytes
        return  chr(0xC0 | (($cp & 0x7C0) >> 6)).
            chr(0x80 | ($cp & 0x3F));
    }else{
        # 1 byte
        return chr($cp);
    }
}
    
function parseHtmlemoji($text){
    $tmpStr = json_encode($text);
    $tmpStr = preg_replace("#(\\\ue[0-9a-f]{3})#ie", "addslashes('\\1')", 
    $tmpStr);
    $text = json_decode($tmpStr);
    preg_match_all("#u([0-9a-f]{4})+#iUs", $text, $rs);
    if (empty($rs[1])) {
        return $text;
    }
    foreach ($rs[1] as $v) {
        $test_iphone = '0x' . trim(strtoupper($v));
        $test_iphone = $test_iphone + 0;
        $t = emoji_unified_to_html(emoji_softbank_to_unified(utf8_bytes($test_iphone)));
        $text = str_replace("\u$v", $t, $text);
    }
    return $text;
}
/*
  对emoji进行转义
*/
function emoji2str($str){
    $strEncode = '';
 
    $length = mb_strlen($str,'utf-8');
 
    for ($i=0; $i < $length; $i++) {
        $_tmpStr = mb_substr($str,$i,1,'utf-8');
        if(strlen($_tmpStr) >= 4){
            $strEncode .= '[[EMOJI:'.rawurlencode($_tmpStr);
        }else{
            $strEncode .= $_tmpStr;
        }
    }
    return $strEncode;
}
/*
读数据后重新转换成emoji返回
*/
function str2emoji($str){
    $str_arr = explode("[[EMOJI:", $str);
    $new_str = "";
 
    foreach ($str_arr as $key => $val){
        $new_str .= $val;
    }
 
    return $new_str;
}
